package com.easypan.utils;

import com.easypan.entity.config.AppConfig;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.enums.FileTypeEnums;
import com.easypan.entity.po.FileInfo;
import com.easypan.exception.BusinessException;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

@Component
public class HadoopUtils {

    private static final Logger logger = LoggerFactory.getLogger(HadoopUtils.class);

    @Resource
    private AppConfig appConfig;

    //上传文件
    public void uploadFile(FileInfo fileInfo) {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", appConfig.getHadoopHdfsUrl());
        try (FileSystem fileSystem = FileSystem.get(conf)) {
            FileTypeEnums fileTypeEnum = FileTypeEnums.getByType(fileInfo.getFileType());
            String fileName = StringTools.getFileNameNoSuffix(fileInfo.getFilePath());
            //视频文件，上传 视频完整文件，视频封面，切片文件
            //1、上传原文件
            copyFromLocalFile(fileSystem, fileInfo.getFilePath());
            //视频文件
            if (FileTypeEnums.VIDEO == fileTypeEnum) {
                //2、上传封面
                String cover = fileName + Constants.IMAGE_PNG_SUFFIX;
                copyFromLocalFile(fileSystem, cover);
                //3、上传切片文件，获取目录下的所有切片文件，都上传
                File folder = new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + fileName);
                File[] listFiles = folder.listFiles();
                if (listFiles != null) {
                    for (File file : listFiles) {
                        copyFromLocalFile(fileSystem, fileName + "/" + file.getName());
                    }
                }
                //删除本地 封面，切片文件
                FileUtils.forceDelete(new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + cover));
                //删除本地目录
                FileUtils.deleteDirectory(folder);
            } else if (FileTypeEnums.IMAGE == fileTypeEnum) {
                //2、上传封面
                String fileSuffix = StringTools.getFileSuffix(fileInfo.getFilePath());
                String coverName = fileName + "_" + fileSuffix;
                copyFromLocalFile(fileSystem, coverName);
                //删除封面
                FileUtils.forceDelete(new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + coverName));
            }
            //删除本地文件
            FileUtils.forceDelete(new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + fileInfo.getFilePath()));
        } catch (Exception e) {
            logger.error("上传文件到hdfs失败", e);
            throw new BusinessException("文件上传失败");
        }
    }

    //上传文件
    private void copyFromLocalFile(FileSystem fileSystem, String filePath) throws IOException {
        fileSystem.copyFromLocalFile(new Path(appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + filePath), new Path("/" + filePath));
    }

    //读取文件
    public void readFileFromHadoop(HttpServletResponse response, String filePath) {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", appConfig.getHadoopHdfsUrl());
        Path hdfsPath = new Path("/" + filePath);
        try (FileSystem fileSystem = FileSystem.get(conf); OutputStream out = response.getOutputStream(); InputStream in = fileSystem.open(hdfsPath)) {
            byte[] byteData = new byte[1024];
            int len = 0;
            while ((len = in.read(byteData)) != -1) {
                out.write(byteData, 0, len);
            }
            out.flush();
        } catch (Exception e) {
            logger.error("从hdfs读取文件失败", e);
            throw new BusinessException("从hdfs读取文件失败");
        }
    }

    //上传头像
    public void uploadAvatar(String userId) {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", appConfig.getHadoopHdfsUrl());
        try (FileSystem fileSystem = FileSystem.get(conf)) {
            String fileName = Constants.FILE_FOLDER_AVATAR_NAME + userId;
            copyFromLocalFile(fileSystem, fileName);
            FileUtils.forceDelete(new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + fileName));
        } catch (Exception e) {
            logger.error("上传头像文件到hdfs失败", e);
            throw new BusinessException("头像文件上传失败");
        }
    }

    //获取头像
    public void readAvatarFromHadoop(HttpServletResponse response, String userId) {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", appConfig.getHadoopHdfsUrl());
        Path hdfsPath = new Path("/" + Constants.FILE_FOLDER_AVATAR_NAME + userId);
        InputStream in = null;
        try (FileSystem fileSystem = FileSystem.get(conf); OutputStream out = response.getOutputStream();) {
            //没有读取到头像，就读取默认头像
            if (!fileSystem.exists(hdfsPath)) {
                in = fileSystem.open(new Path("/" + Constants.FILE_FOLDER_AVATAR_NAME + Constants.AVATAR_DEFUALT));
            } else {
                in = fileSystem.open(hdfsPath);
            }
            byte[] byteData = new byte[1024];
            int len = 0;
            while ((len = in.read(byteData)) != -1) {
                out.write(byteData, 0, len);
            }
            out.flush();
            in.close();
        } catch (Exception e) {
            logger.error("从hdfs读取文件失败", e);
            throw new BusinessException("从hdfs读取文件失败");
        }
    }

    public static void main(String[] args) throws IOException {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://localhost:9000"); // HDFS的URI

        // 创建FileSystem实例
        FileSystem fileSystem = FileSystem.get(conf);

        // 上传文件
        fileSystem.copyFromLocalFile(new Path("C:\\test.jpg"), new Path("/test/test.jpg"));

        System.out.println("上传成功");

        Path hdfsPath = new Path("/test/test.jpg");
        InputStream inStream = fileSystem.open(hdfsPath);
    }
}
